package com.otherTest.java8;
/*
 * Copyright (c) 2018  菠菜数块链版权所有.
 */
import java.math.BigDecimal;
import java.util.Collections;
import java.util.Set;
import java.util.function.BiConsumer;
import java.util.function.BinaryOperator;
import java.util.function.Function;
import java.util.function.Supplier;
import java.util.stream.Collector;
/**
 * @Description:
 * @author: conceit
 * @Date: 2018/10/11 0011 11:59
 */
public class CollectorsUtil {

        static final Set<Collector.Characteristics> CH_NOID = Collections.emptySet();

        private CollectorsUtil() {
        }

        @SuppressWarnings("unchecked")
        private static <I, R> Function<I, R> castingIdentity() {
            return i -> (R) i;
        }

        /**
         * Simple implementation class for {@code Collector}.
         *
         * @param <T>
         *            the type of elements to be collected
         * @param <R>
         *            the type of the result
         */
        static class CollectorImpl<T, A, R> implements Collector<T, A, R> {
            private final Supplier<A> supplier;
            private final BiConsumer<A, T> accumulator;
            private final BinaryOperator<A> combiner;
            private final Function<A, R> finisher;
            private final Set<Characteristics> characteristics;

            CollectorImpl(Supplier<A> supplier, BiConsumer<A, T> accumulator, BinaryOperator<A> combiner,
                          Function<A, R> finisher, Set<Characteristics> characteristics) {
                this.supplier = supplier;
                this.accumulator = accumulator;
                this.combiner = combiner;
                this.finisher = finisher;
                this.characteristics = characteristics;
            }

            CollectorImpl(Supplier<A> supplier, BiConsumer<A, T> accumulator, BinaryOperator<A> combiner,
                          Set<Characteristics> characteristics) {
                this(supplier, accumulator, combiner, castingIdentity(), characteristics);
            }

            @Override
            public BiConsumer<A, T> accumulator() {
                return accumulator;
            }

            @Override
            public Supplier<A> supplier() {
                return supplier;
            }

            @Override
            public BinaryOperator<A> combiner() {
                return combiner;
            }

            @Override
            public Function<A, R> finisher() {
                return finisher;
            }

            @Override
            public Set<Characteristics> characteristics() {
                return characteristics;
            }
        }

        public static <T> Collector<T, ?, BigDecimal> summingBigDecimal(ToBigDecimalFunction<? super T> mapper) {
            return new CollectorImpl<>(() -> new BigDecimal[1], (a, t) -> {
                if (a[0] == null) {
                    a[0] = BigDecimal.ZERO;
                }
                a[0] = a[0].add(mapper.applyAsBigDecimal(t));
            }, (a, b) -> {
                a[0] = a[0].add(b[0]);
                return a;
            }, a -> a[0], CH_NOID);
        }
    }
